/*
 * Copyright (c) 2014-2019 2018 xmars All Rights Reserved.
 * ProjectName: xmars
 * FileName: ImageUtil.java
 * Author: pipi
 * Date: 18-12-13 下午6:51
 * Version: 1.0
 * LastModified: 18-12-5 下午2:29
 */

package com.topsun.framework.common.core.util;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.topsun.framework.common.core.enums.ContentTypeEnum;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.*;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

public class ImageUtil {
    public static final String BMP = "bmp";
    public static final String JPG = "jpg";
    public static final String PNG = "png";
    public static final String GIF = "gif";

    private final static Logger log = LoggerFactory.getLogger(ImageUtil.class);

    public static final Set<String> IMAGE_TYPE;

    static {
        IMAGE_TYPE = new HashSet<>();
        IMAGE_TYPE.add("jpg");
        IMAGE_TYPE.add("jpeg");
        IMAGE_TYPE.add("png");
        IMAGE_TYPE.add("bmp");
        IMAGE_TYPE.add("gif");
        IMAGE_TYPE.add("tif");
        IMAGE_TYPE.add("emf");
    }

    private ImageUtil() {
    }

    /**
     * 根据字节流判断图片文件类型
     *
     * @param fileBytes 文件字节流
     * @return 文件类型
     */
    public static String getFileSuffix(byte[] fileBytes) {
        if (fileBytes == null || fileBytes.length < 10) {
            return null;
        }

        if (fileBytes[0] == 'B' && fileBytes[1] == 'M') {
            return BMP;
        } else if ((fileBytes[0] & 0xFF) == 0xFF && (fileBytes[1] & 0xFF) == 0xD8 && (fileBytes[fileBytes.length - 2] & 0xFF) == 0xFF
                && (fileBytes[fileBytes.length - 1] & 0xFF) == 0xD9) {
            return JPG;
        } else if (fileBytes[1] == 'P' && fileBytes[2] == 'N' && fileBytes[3] == 'G') {
            return PNG;
        } else if (fileBytes[0] == 'G' && fileBytes[1] == 'I' && fileBytes[2] == 'F') {
            return GIF;
        } else {
            return null;
        }
    }



    /**
     * 判断文件是不是图片
     * @param file
     * @return
     */
    public static boolean isImage(File file) {
        return IMAGE_TYPE.contains(FileTypeUtil.getType(file));
    }

    /**
     * 判断文件是不是图片
     * @param inputStream
     * @return
     */
    public static boolean isImage(InputStream inputStream) {
        return IMAGE_TYPE.contains(FileTypeUtil.getType(inputStream, true));
    }

    /**
     * 判断文件是不是图片
     * @param bytes
     * @return
     */
    public static boolean isImage(byte[] bytes) {
        return isImage(new ByteArrayInputStream(bytes));
    }

    /**
     * 图片的二进制数据转base64
     * @param imageBytes
     * @return
     */
    public static String imageBytesToBase64(byte[] imageBytes) {
        InputStream inputStream = new ByteArrayInputStream(imageBytes);
        return imageToBase64(inputStream);
    }

    /**
     * 图片文件绝对路径转base64
     * @param imagePath
     * @return
     */
    public static String imagePathToBase64(String imagePath) {
        try {
            FileInputStream inputStream = new FileInputStream(imagePath);
            return imageToBase64(inputStream);
        } catch (FileNotFoundException e) {
            log.error("文件不存在！imagePath is:{}", imagePath, e);
            return null;
        }
    }

    /**
     * 图片转base64
     * @param file
     * @return
     */
    public static String imageFileToBase64(File file) {
        try {
            InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
            return imageToBase64(inputStream);
        } catch (FileNotFoundException e) {
            log.error("文件不存在！file is:{}", JSON.toJSONString(file), e);
            return null;
        }
    }

    /**
     * 图片Url转base64
     * @param imgUrlPath
     * @return
     */
    public static String imageUrlToBase64(String imgUrlPath) {
        try {
            InputStream inputStream = new URL(imgUrlPath).openConnection().getInputStream();
            return imageToBase64(inputStream);
        } catch (IOException e) {
            log.error("图片转换异常！imgUrlPath is:{}", imgUrlPath, e);
            return null;
        }
    }

    /**
     * 图片转base64
     * @param inputStream
     * @return
     */
    public static String imageToBase64(InputStream inputStream) {
        try {
            byte[] byteDate = new byte[inputStream.available()];
            inputStream.read(byteDate);
            return new BASE64Encoder().encode(byteDate);
        } catch (IOException e) {
            log.error("图片转换异常！", e);
            return null;
        } finally {
            if (ObjectUtil.isNotNull(inputStream)) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }

    /**
     * base64转图片二进制
     * @param imgStr
     * @return
     */
    public static byte[] base64ToImageByte(String imgStr) {
        if (StrUtil.isBlank(imgStr)) {
            return null;
        }
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            //Base64解码
            byte[] b = decoder.decodeBuffer(imgStr);
            for (int i = 0; i < b.length; ++i) {
                //调整异常数据
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            return b;
        } catch (IOException e) {
            log.error("base64转图片二进制", e);
            return null;
        }
    }

    /**
     * 获取base64的mimeType
     * @param imgStr
     * @return
     */
    public static String getBase64MimeType(String imgStr) {
        if (imgStr.startsWith("data:")) {
            return imgStr.substring(imgStr.indexOf(":") + 1, imgStr.indexOf(";"));
        }
        return ContentTypeEnum.IMAGE_JEPG.getType();
    }

    /**
     * 图片压缩
     * @param file
     * @return
     * @throws IOException
     */
    public static byte[] compress(File file) throws IOException {
        return compress(Thumbnails.of(file));
    }

    /**
     * 图片压缩
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] compress(InputStream inputStream) throws IOException {
        return compress(Thumbnails.of(inputStream));
    }

    /**
     * 图片压缩
     * @param imageByte
     * @return
     * @throws IOException
     */
    public static byte[] compress(byte[] imageByte) throws IOException {
        return compress(new ByteArrayInputStream(imageByte));
    }

    /**
     * 图片质量压缩25%，比例大小不变
     * @param builder
     * @return
     * @throws IOException
     */
    private static byte[] compress(Thumbnails.Builder<?> builder) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        builder.scale(1F).outputQuality(0.5F).toOutputStream(byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }


    /**
     * 缩略图
     * @param file
     * @return
     * @throws IOException
     */
    public static byte[] thumbnail(File file) throws IOException {
        return thumbnail(Thumbnails.of(file));
    }

    /**
     * 缩略图
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] thumbnail(InputStream inputStream) throws IOException {
        return thumbnail(Thumbnails.of(inputStream));
    }

    /**
     * 缩略图
     * @param imageByte
     * @return
     * @throws IOException
     */
    public static byte[] thumbnail(byte[] imageByte) throws IOException {
        return thumbnail(new ByteArrayInputStream(imageByte));
    }

    private static byte[] thumbnail(Thumbnails.Builder<?> builder) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        builder.scale(0.2F).toOutputStream(byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }
}
